package com.sparrow.resource.convert;

import com.sparrow.common.util.JsonUtil;
import com.sparrow.common.value.EnumUtil;
import com.sparrow.resource.annotation.Convert;
import com.sparrow.resource.convert.impl.IntArrayConverter;
import org.springframework.core.convert.converter.Converter;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 配置值转换器
 */
public class ValueConverter {

    private static ConcurrentHashMap<Class<?>, Converter> converters = new ConcurrentHashMap<>();

    /**
     * 将字符串转换为指定类型的对象。
     *
     * @param str     要转换的字符串
     * @param typeStr 目标类型的字符串表示
     * @param field   字段对象
     * @return 转换后的对象
     * @throws RuntimeException 如果无法识别类型或转换过程中出现异常
     */
    public static Object convertVal(String colName, String str, String typeStr, Field field) {
        // 确保输入参数不为空
        Objects.requireNonNull(str, "输入字符串不能为 null");
        Objects.requireNonNull(typeStr, "类型字符串不能为 null");
        Objects.requireNonNull(field, "配置Class字段缺失字段 配置列名=" + colName);
        Class<?> type = field.getType();
        if (EnumUtil.isEnum(type)) {//优先处理注解
            return EnumUtil.parseEnum(type, str);
        }
        try {
            switch (typeStr) {
                case "boolean": {
                    return Byte.valueOf(str) == 1;
                }
                case "byte":
                    return Byte.valueOf(str);
                case "short":
                    return Short.valueOf(str);
                case "int":
                    return Integer.valueOf(str);
                case "long":
                    return Long.valueOf(str);
                case "float":
                    return Float.valueOf(str);
                case "double":
                    return Double.valueOf(str);
                case "string": {
                    //转换值
                    Convert an = field.getAnnotation(Convert.class);
                    if (an != null) {
                        try {
                            Class<? extends Converter> convertClass = an.value();
                            Converter converter = converters.computeIfAbsent(convertClass, k -> {
                                try {
                                    return (Converter) convertClass.getConstructors()[0].newInstance();
                                } catch (Exception e) {
                                    throw new RuntimeException(e);
                                }
                            });
                            Object convert = converter.convert(str);
                            return convert;
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
                    return str;
                }
                case "int[]": {
                    Converter converter = converters.computeIfAbsent(IntArrayConverter.class, k -> {
                        try {
                            return (Converter) IntArrayConverter.class.getConstructors()[0].newInstance();
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    });
                    Object convert = converter.convert(str);
                    return convert;
                }
                case "json": {
                    if (List.class.isAssignableFrom(type)) {
                        Type[] pt = getParameterizedType(field);
                        return JsonUtil.parseList(str, (Class<?>) pt[0]);
                    } else if (Set.class.isAssignableFrom(type)) {
                        Type[] pt = getParameterizedType(field);
                        return JsonUtil.parseSet(str, (Class<?>) pt[0]);
                    } else if (Map.class.isAssignableFrom(type)) {
                        Type[] pt = getParameterizedType(field);
                        return JsonUtil.parseMap(str, (Class<?>) pt[0], (Class<?>) pt[1]);
                    } else {
                        return JsonUtil.parse(str, type);
                    }
                }
                default:
                    throw new RuntimeException(String.format("无法识别的类型: %s", typeStr));
            }
        } catch (NumberFormatException e) {
            throw new RuntimeException(String.format("无法将 %s 转换为 %s 类型", str, typeStr), e);
        }
    }

    // 将 Field 的类型转换为 typeStr
    public static String mapFieldType(Field field) {
        Class<?> type = field.getType();
        if (type == boolean.class || type == Boolean.class) return "boolean";
        if (type == byte.class || type == Byte.class) return "byte";
        if (type == short.class || type == Short.class) return "short";
        if (type == int.class || type == Integer.class) return "int";
        if (type == long.class || type == Long.class) return "long";
        if (type == float.class || type == Float.class) return "float";
        if (type == double.class || type == Double.class) return "double";
        if (type == String.class) return "string";
        if (type.isArray() && type.getComponentType() == int.class) return "int[]";
        if (Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type)) return "json";
        if (type.isEnum()) return "string"; // 枚举按 string 处理
        return "string"; // 默认当作字符串处理
    }

    /**
     * 获取字段的泛型实际类型参数。
     *
     * @param field 字段对象
     * @return 泛型实际类型参数数组
     * @throws RuntimeException 如果字段没有泛型参数
     */
    public static Type[] getParameterizedType(Field field) {
        // 确保字段对象不为空
        Objects.requireNonNull(field, "字段对象不能为 null");

        Type genericType = field.getGenericType();
        if (genericType instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) genericType;
            // 获取泛型类型的实际类型参数
            return parameterizedType.getActualTypeArguments();
        }
        throw new RuntimeException("没有泛型参数");
    }
}